package net.moao.netutils_library.tcp;

import android.util.Log;

import net.moao.netutils_library.NetUtils;

import java.io.UnsupportedEncodingException;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * TCPClientThread
 *
 * @author Moao.Net
 * @DATE 2024/6/10
 */
public class TCPClientThread extends Thread {
    private static final String TAG = "TCPClientThread";
    private TCPClient tcpClient;
    private final boolean isDomain;
    private String tcpServerDomainName;
    private String tcpServerIP;
    private final int tcpServerPort;
    private int soTimeout = 2000;  // 接收 超时时间
    private final TCPClientThreadCallback callback;

    /**
     * 有参构造
     * @param isDomain 是否为域名
     * @param tcpServerDomainOrIP 要连接的域名或者IP
     * @param tcpServerPort 要连接的端口
     * @param soTimeout 设置接收 超时 时间，多久没收到消息，重新接收，心跳包用处大，打包有问题时也可以改这个
     * @param callback 回调函数
     */
    public TCPClientThread(boolean isDomain, String tcpServerDomainOrIP, int tcpServerPort, Integer soTimeout, TCPClientThreadCallback callback) {
        this.isDomain = isDomain;
        if (isDomain){
            this.tcpServerDomainName = tcpServerDomainOrIP;
        }else {
            this.tcpServerIP = tcpServerDomainOrIP;
        }
        this.tcpServerPort = tcpServerPort;
        if (soTimeout != null){
            this.soTimeout = soTimeout;
        }
        this.callback = callback;
    }

    @Override
    public void run() {
        // 线程执行的代码逻辑
        super.run();
        // 检查线程是否被中断
        conn();
        while (!isInterrupted()) {
            // 线程正常工作
            if (tcpClient.isConnTCP){
                byte[] msgBytes = tcpClient.receive();
                String msgStr = new String(msgBytes);
                if (msgStr.equals("java.net.SocketTimeoutException: Read timed out")){
//                    Log.d(TAG, "接收超时");
                    if (callback != null) {
                        Log.d(TAG, "调用 心跳包 回调函数");
                        callback.onHeartbeat(tcpClient); // 调用 心跳包 回调函数
                    }
                }else if (msgStr.equals("java.net.SocketException: Connection reset")){
                    Log.d(TAG, "断开链接！");
                    break;
                }else {
                    Log.d(TAG, "收到 : " + msgStr + "默认编码");
                    try {
                        Log.d(TAG, "收到 : " + new String(msgBytes, "GBK") + "GBK编码");
                    } catch (UnsupportedEncodingException e) {
                        Log.d(TAG, "GBK编码 解码失败！");
                        throw new RuntimeException(e);
                    }
                    if (callback != null) {
                        Log.d(TAG, "调用接收回调函数");
                        callback.onReceive(msgBytes); // 调用回调函数
                    }
                }
            }else {
                Log.d(TAG, "TCP 断开链接");
                conn();
            }
        }
        // 如果需要在线程停止时执行特定的函数，可以在此处添加代码
        if (callback != null) {
            Log.d(TAG, "调用最后执行回调函数");
            callback.onRunLast(tcpClient.isConnTCP); // 调用回调函数
        }

        Log.d(TAG, "线程终止");
        // 线程停止后执行的代码逻辑
        tcpClient.closed();
    }

    /**
     * 连接 服务器
     */
    private void conn(){
        if (isDomain){
            tcpServerIP = NetUtils.Domain2IP(tcpServerDomainName);
        }
        tcpClient = new TCPClient();
        boolean isConn = tcpClient.connect(tcpServerIP, tcpServerPort, soTimeout);
        if (callback != null) {
            Log.d(TAG, "调用连接完成回调函数");
            callback.onConn(isConn);
        }
    }

    /**
     * 发送数据
     */
    public boolean send(String str) throws InterruptedException {
        AtomicBoolean flag = new AtomicBoolean(false);
        Thread thread = new Thread(()->{
            if (tcpClient.isConnTCP){
                tcpClient.send(str);
                flag.set(true);
            }else {
                flag.set(false);
            }
        });
        thread.start();
        thread.join();
        return flag.get();
    }

    /**
     * 发送数据
     */
    public boolean sendHexMessage(byte[] message) throws InterruptedException {
        AtomicBoolean flag = new AtomicBoolean(false);
        Thread thread = new Thread(()->{
            if (tcpClient.isConnTCP){
                tcpClient.sendHexMessage(message);
                flag.set(true);
            }else {
                flag.set(false);
            }
        });
        thread.start();
        thread.join();
        return flag.get();
    }
}
